/*
 * ScriptManager.cpp
 *
 *  Created on: 2009/02/05
 *      Author: Yongshik Cho
 */

#include "ScriptManager.h"
#include "LoggerableManager.h"
#include "Camera.h"
#include "Tile.h"
#include "Sprite.h"
#include "TextObject.h"
#include "Tilemap.h"
#include "RenderDevice.h"
#include "TextureManager.h"
#include "SceneManager.h"
#include "SoundManager.h"
#include "WorldManager.h"
#include "xml/SpriteLoader.h"
#include "xml/TilemapLoader.h"

#define SQ_REG_CONST_STATIC_VAR


template<> ScriptManager* ISingleton<ScriptManager>::m_pInstance = 0;

/*
 *	about squirrel bindings (2009/02/19 Yongshik Cho)
 *
 *	- native type is not bindable as a const argument (it occurs compile error) 
 *	  or pointer type (it occurs link error)
 *
 *	- std::string is bindable as a const std::string& or std::string& 
 *	  but not as std::string* (it occurs link error)
 *
 *	- user define object is bindable as a const object& or object& or object*
 *
 */

ScriptManager::ScriptManager()
{
	// TODO Auto-generated constructor stub
	SquirrelVM::Init();

	if(SquirrelVM::IsInitialized())
		mInitialized = true;
	else
		mInitialized = false;

	AltoLog("ScriptManager has been initialized.");
}

ScriptManager::~ScriptManager()
{
	// TODO Auto-generated destructor stub
	mScriptObjects.clear();

	if(mInitialized)
		SquirrelVM::Shutdown();

	AltoLog("ScriptManager has been shutdown.");
}

void ScriptManager::load(const String& path)
{
	if(!mInitialized)
		return;

	if(isExists(path))
		return;

	//compile script file
	SquirrelObject object = SquirrelVM::CompileScript(path.c_str());
	mScriptObjects[path] =  object;

	//run script object
	SquirrelVM::RunScript(object);
}

bool ScriptManager::isExists(const String& path)
{
	for(map<String, SquirrelObject>::iterator it=mScriptObjects.begin();it!=mScriptObjects.end();++it)
	{
		if((*it).first == path)
			return true;
	}

	return false;
}

void ScriptManager::bindScriptClasses()
{
	bindManagers();
	bindCoreClasses();
	bindActiveClasses();
	bindXmlClasses();
	bindAltoClasses();
}

void ScriptManager::bindManagers()
{
	//bind TextureManager
	SQClassDef<TextureManager>(_T("TextureManager"))
		.staticFunc(&TextureManager::GetInstancePtr, _T("GetInstance"))
		.func(&TextureManager::load, _T("Load"))
		.func(&TextureManager::getTextureCount, _T("GetTextureCount"))
		;

	//bind SoundManager
	SQClassDef<SoundManager>(_T("SoundManager"))
		.staticFunc(&SoundManager::GetInstancePtr, _T("GetInstance"))
		.func(&SoundManager::load, _T("Load"))
		.func(&SoundManager::getSoundCount, _T("GetSoundCount"))
		;

	//bind SceneManager
	SQClassDef<SceneManager>(_T("SceneManager"))
		.staticFunc(&SceneManager::GetInstancePtr, _T("GetInstance"))
		.func(&SceneManager::getRenderRoot, _T("GetRenderRoot"))
		.func(&SceneManager::getActiveCamera, _T("GetActiveCamera"))
		.func(&SceneManager::getCamera, _T("GetCamera"))
		.func(&SceneManager::addCamera, _T("AddCamera"))
		.func(&SceneManager::subCamera, _T("SubCamera"))
		.func(&SceneManager::getCameraCount, _T("GetCameraCount"))
		.func(&SceneManager::clear, _T("Clear"))
		;

	//bind SoundManager
	SQClassDef<LoggerableManager>(_T("LoggerableManager"))
		.staticFunc(&LoggerableManager::GetInstancePtr, _T("GetInstance"))
		//.func(&LoggerableManager::add, _T("Add"))
		//.func(&LoggerableManager::sub, _T("Sub"))
		.func(&LoggerableManager::print, _T("Print"))
		;

	SQClassDef<WorldManager>(_T("WorldManager"))
		.staticFunc(&WorldManager::GetInstancePtr, _T("GetInstance"))
		.func(&WorldManager::getWorldCount, _T("GetWorldCount"))
		.func(&WorldManager::getWorld, _T("GetWorld"))
		.func(&WorldManager::addWorld, _T("AddWorld"))
		;

}

void ScriptManager::bindCoreClasses()
{
	SQClassDef<Vector2D>(_T("Vector2D"))
	    .func(&Vector2D::length, _T("length"))
	    .var(&Vector2D::x, _T("x"))
	    .var(&Vector2D::y, _T("y"))
	    ;

	SQClassDef<Color>(_T("Color"))
		/* only static member constant can be defined as script constant.
		.constant(Color::BLEND_NONE, _T("BLEND_NONE"))
		.constant(Color::BLEND_ALPHA, _T("BLEND_ALPHA"))
		.constant(Color::BLEND_ADD, _T("BLEND_ADD"))
		.constant(Color::BLEND_SUB, _T("BLEND_SUB"))
		.constant(Color::BLEND_DARKEN, _T("BLEND_DARKEN"))
		.constant(Color::BLEND_LIGHTEN, _T("BLEND_LIGHTEN"))
		.constant(Color::BLEND_MULTIPLY, _T("BLEND_MULTIPLY"))
		.constant(Color::BLEND_SCREEN, _T("BLEND_SCREEN"))
		.constant(Color::BLEND_DIFFERENCE, _T("BLEND_DIFFERENCE"))
		.constant(Color::BLEND_INVERSE_DIFFERENCE, _T("BLEND_INVERSE_DIFFERENCE"))
		.constant(Color::BLEND_INVERT, _T("BLEND_INVERT"))
		.constant(Color::BLEND_DODGE, _T("BLEND_DODGE"))
		*/
		.staticFunc(&Color::fromUint, _T("FromUint"))
		.staticFunc(&Color::fromRGB, _T("FromRGB"))
		.staticFunc(&Color::fromRGBA, _T("FromRGBA"))
		.staticFunc(&Color::fromARGB, _T("FromARGB"))
		.func(&Color::getRGBA, _T("GetRGBA"))
		.var(&Color::r, _T("r"))
		.var(&Color::g, _T("g"))
		.var(&Color::b, _T("b"))
		.var(&Color::a, _T("a"))
	    ;

}

void ScriptManager::bindActiveClasses()
{
	SQClassDef<Renderable>(_T("Renderable"))
		.func(&Renderable::getPosition, _T("getPosition"))
		.func(&Renderable::animate_bindable, _T("Animate"))
		.func(&Renderable::tween_bindable, _T("Tween"))
		.func(&Renderable::playback_bindable, _T("Playback"))
		.func(&Renderable::setAlpha, _T("SetAlpha"))
		.func(&Renderable::getAttachmentByName, _T("GetAttachmentByName"))
		;

	SQClassDef<Tweenable>(_T("Tweenable"))
		.func(&Tweenable::tween, _T("Tween"))
		.func(&Tweenable::addRenderable, _T("AddRenderable"))
		.func(&Tweenable::subRenderable, _T("SubRenderable"))
		;
/*
	SQClassDef<Loggerable>(_T("Loggerable"))
		.func(&Loggerable::getPath, _T("GetPath"))
		;
*/
}

void ScriptManager::bindXmlClasses()
{
	SQClassDef<SpriteLoader>(_T("SpriteLoader"))
		.staticFunc(&SpriteLoader::load, _T("Load"))
		;

	SQClassDef<TilemapLoader>(_T("TilemapLoader"))
		.staticFunc(&TilemapLoader::load, _T("Load"))
		;
}

void ScriptManager::bindAltoClasses()
{
/*
	//bind Texture
	SQClassDef<Texture>(_T("Texture"))
		.func(&Texture::getId, _T("GetId"))
		.func(&Texture::getPath, _T("GetPath"))
		.func(&Texture::getWidth, _T("GetWidth"))
		.func(&Texture::getHeight, _T("GetHieght"))
		.func(&Texture::getFormat, _T("GetFormat"))
		.func(&Texture::getScaledWidth, _T("GetScaledWidth"))
		.func(&Texture::getScaledHeight, _T("GetScaledHeight"))
		.func(&Texture::getRowBytes, _T("GetRowBytes"))
		.func(&Texture::getPixelColor, _T("GetPixelColor"))
		.func(&Texture::setTransparentColor, _T("SetTransparentColor"))
		;

	//bind Sound
	SQClassDef<Sound>(_T("Sound"))
		.func(&Sound::getId, _T("GetId"))
		.func(&Sound::getPath, _T("GetPath"))
		.func(&Sound::getFormat, _T("GetFormat"))
		.func(&Sound::getRate, _T("GetRate"))
		.func(&Sound::getQueueCount, _T("GetQueueCount"))
		;
*/
	//bind RenderDevice
	SQClassDef<RenderDevice>(_T("RenderDevice"))
		.staticFunc(&RenderDevice::GetInstancePtr, _T("GetInstance"))
		.func(&RenderDevice::drawRect, _T("DrawRect"))
		.func(&RenderDevice::drawFillRect, _T("DrawFillRect"))
		.func(&RenderDevice::drawBezier, _T("DrawBezier"))
		.func(&RenderDevice::drawFillBezier, _T("DrawFillBezier"))
		.func(&RenderDevice::drawPath, _T("DrawPath"))
		;

	//bind Camera
	SQClassDef<Camera>(_T("Camera"))
		.func(&Camera::getScale, _T("GetScale"))
		.func(&Camera::setScale, _T("SetScale"))
		;

	//bind SceneManager
	SQClassDef<RenderObject, Renderable>(_T("RenderObject"))
		.func(&RenderObject::buildQuadtree, _T("BuildQuadtree"))
		.func(&RenderObject::getChildByName, _T("GetChildByName"))
		.func(&RenderObject::getPathByName, _T("GetPathByName"))
		;

	//bind SceneManager
	SQClassDef<RenderObjectContainer, RenderObject>(_T("RenderObjectContainer"))
		.func(&RenderObjectContainer::addChild, _T("AddChild"))
		.func(&RenderObjectContainer::subChild, _T("SubChild"))
		.func(&RenderObjectContainer::getChildCount, _T("GetChildCount"))
		.func(&RenderObjectContainer::getChild, _T("GetChild"))
		.func(&RenderObjectContainer::buildQuadtree, _T("BuildQuadtree"))
		.func(&RenderObjectContainer::clearQuadtree, _T("ClearQuadtree"))
		;

	//bind Tile
	SQClassDef<Path>(_T("Path"))
		.func(&Path::tween, _T("Tween"))
		.func(&Path::addRenderable, _T("AddRenderable"))
		.func(&Path::subRenderable, _T("SubRenderable"))
		.func(&Path::getName, _T("GetName"))
		.func(&Path::getAttachment, _T("GetAttachment"))
		.func(&Path::setAttachment, _T("SetAttachment"))
		;

	//bind Tile
	SQClassDef<Tile, RenderObject>(_T("Tile"))
		.func(&Tile::getAnimationCount, _T("GetAnimationCount"))
		;

	//bind Sprite
	SQClassDef<Sprite, RenderObjectContainer>(_T("Sprite"))
		.func(&Sprite::getPathCount, _T("GetPathCount"))
		.func(&Sprite::getPath, _T("GetPath"))
		.func(&Sprite::addPath, _T("AddPath"))
		;

	//bind TextObject
	SQClassDef<TextObject, RenderObject>(_T("TextObject"))
		.func(&TextObject::getLineColor, _T("GetLineColor"))
		.func(&TextObject::setLineColor, _T("SetLineColor"))
		.func(&TextObject::getFillColor, _T("GetFillColor"))
		.func(&TextObject::setFillColor, _T("SetFillColor"))
		.func(&TextObject::getLineStyle, _T("GetLineStyle"))
		.func(&TextObject::setLineStyle, _T("SetLineStyle"))
		.func(&TextObject::getFillStyle, _T("GetFillStyle"))
		.func(&TextObject::setFillStyle, _T("SetFillStyle"))
		;

	//bind Shape
	SQClassDef<ShapeObject, RenderObject>(_T("ShapeObject"))
		.func(&ShapeObject::getLineColor, _T("GetLineColor"))
		.func(&ShapeObject::setLineColor, _T("SetLineColor"))
		.func(&ShapeObject::getFillColor, _T("GetFillColor"))
		.func(&ShapeObject::setFillColor, _T("SetFillColor"))
		.func(&ShapeObject::getLineStyle, _T("GetLineStyle"))
		.func(&ShapeObject::setLineStyle, _T("SetLineStyle"))
		.func(&ShapeObject::getFillStyle, _T("GetFillStyle"))
		.func(&ShapeObject::setFillStyle, _T("SetFillStyle"))
		.func(&ShapeObject::getLineWidth, _T("GetLineWidth"))
		.func(&ShapeObject::setLineWidth, _T("SetLineWidth"))
		;

	//bind Shape
	SQClassDef<World>(_T("World"))
		.func(&World::getGravity, _T("GetGravity"))
		.func(&World::setGravity, _T("SetGravity"))
		.func(&World::getWind, _T("GetWind"))
		.func(&World::setWind, _T("SetWind"))
		.func(&World::addBody, _T("AddBody"))
		;

	//bind Tilemap
	SQClassDef<Tilemap, RenderObjectContainer>(_T("Tilemap"))
		.func(&Tilemap::getPathCount, _T("GetPathCount"))
		.func(&Tilemap::getPath, _T("GetPath"))
		.func(&Tilemap::addPath, _T("AddPath"))
		;
}
